package execlutil

import (
	"fmt"
	"gitee.com/zhongguo168a/gocodes/datax"
	"gitee.com/zhongguo168a/gocodes/datax/convertx"
	"github.com/xuri/excelize/v2"
	"os"
	"strings"
)

func isType(coltyp string) bool {
	typArr := strings.Split(coltyp, ",")
	typ := typArr[0]
	switch typ {
	case "int":
		return true
	case "string":
		return true
	case "bool":
		return true
	case "float":
		return true
	case "percent":
		return true
	}

	return false
}

func 检查和整理(file, sheet string, rows [][]string) (titles []string, types []string) {

	row0 := rows[0]
	for _, val := range row0 {
		titles = append(titles, val)
	}
	row2 := rows[2]
	var hasErr bool
	for i, val := range row2 {
		key := titles[i]
		if val == "" {
			hasErr = true
			fmt.Printf("%v-%v: 未设置字段类型：字段=%v, 值=%v\n", file, sheet, key, val)
			continue
		}
		if !isType(val) {
			hasErr = true
			fmt.Printf("%v-%v: 不支持的类型：字段=%v，类型=%v\n", file, sheet, key, val)
		}
		types = append(types, val)
	}
	if hasErr {
		os.Exit(-1)
	}

	return
}

func ExeclToMap(file string) datax.M {
	f, err := excelize.OpenFile(file)
	if err != nil {
		return nil
	}
	defer func() {
		// Close the spreadsheet.
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	result := datax.M{}
	for _, sheet := range f.GetSheetList() {
		if string(sheet[0]) == "_" {
			continue
		}
		rows, _ := f.GetRows(sheet)
		if len(rows) == 0 {
			fmt.Printf("[WARN] %v-%v: 空表\n", file, sheet)
			continue
		}

		titles, types := 检查和整理(file, sheet, rows)

		sheetMap := make(datax.A, len(rows)-3)
		result[sheet] = sheetMap
		rowMax := len(titles)
		{
			colList := make(datax.A, rowMax, rowMax)
			sheetMap[0] = colList
			for i, title := range titles {
				colList[i] = title
			}
		}
		{
			colList := make(datax.A, rowMax, rowMax)
			sheetMap[1] = colList
			for i, typ := range types {
				colList[i] = typ
			}
		}

		rows = rows[3:]
		for rIndex, row := range rows {
			colMap := datax.M{}
			sheetMap[rIndex] = colMap
			for i := 0; i < len(titles); i++ {
				key := titles[i]
				typ := types[i]
				colMap[key] = func() (x interface{}) {

					x = row[i]
					switch typ {
					case "int":
						x = convertx.AnyToInt(x)
					case "float":
						x = convertx.AnyToFloat64(x)
					case "percent":
						x = convertx.AnyToFloat64(x)
					case "bool":
						x = convertx.AnyToBool(x)
					case "string":
						x = convertx.AnyToString(x)
					default:

					}

					return
				}()
			}
		}
	}

	return result
}

func ExeclToTable(file string) datax.M {
	f, err := excelize.OpenFile(file)
	if err != nil {
		return nil
	}
	defer func() {
		// Close the spreadsheet.
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	result := datax.M{}
	for _, sheet := range f.GetSheetList() {
		if string(sheet[0]) == "_" {
			continue
		}

		rows, _ := f.GetRows(sheet)
		if len(rows) == 0 {
			fmt.Printf("[WARN] %v-%v: 空表\n", file, sheet)
			continue
		}
		titles, types := 检查和整理(file, sheet, rows)
		sheetMap := make(datax.A, len(rows)-1)
		result[sheet] = sheetMap

		rowMax := len(titles)
		{
			colList := make(datax.A, rowMax, rowMax)
			sheetMap[0] = colList
			count := 0
			for i, title := range titles {
				if string(titles[i]) == "_" {
					continue
				}
				colList[count] = title
				count++
			}
		}
		{
			colList := make(datax.A, rowMax, rowMax)
			sheetMap[1] = colList
			count := 0
			for i, typ := range types {
				if string(titles[i]) == "_" {
					continue
				}
				colList[count] = typ
				count++
			}
		}
		rows = rows[3:]
		for rIndex, row := range rows {
			colList := make(datax.A, rowMax, rowMax)
			sheetMap[rIndex+2] = colList
			count := 0
			for i := 0; i < len(titles); i++ {
				if string(titles[i]) == "_" {
					continue
				}
				coltyp := types[i]
				if coltyp == "" {
					coltyp = "string"
				}
				typArr := strings.Split(coltyp, ",")
				typ := typArr[0]
				colList[count] = func() (x interface{}) {
					if i >= len(row) {
						x = ""
					} else {
						x = row[i]
					}

					switch typ {
					case "int":
						x = convertx.AnyToInt(x)
					case "float":
						x = convertx.AnyToFloat64(x)
					case "percent":
						x = convertx.AnyToFloat64(x)
					case "bool":
						x = convertx.AnyToBool(x)
					case "string":
						x = convertx.AnyToString(x)
					default:
					}

					return
				}()
				count++
			}
		}
	}

	return result
}
